
#include "wiacommon.h"

#include "DataCallback.h"
//#include "ProgressDlg.h"

#ifndef MAX_GUID_STRING_LEN
#define MAX_GUID_STRING_LEN 39
#endif //MAX_GUID_STRING_LEN


HRESULT ReadPropertyLong( IWiaPropertyStorage *pWiaPropertyStorage, const PROPSPEC *pPropSpec, LONG *plResult )
{
    PROPVARIANT PropVariant;

    HRESULT hr = pWiaPropertyStorage->ReadMultiple( 1, pPropSpec, &PropVariant );

    // Generally, the return value should be checked against S_FALSE.
    // If ReadMultiple returns S_FALSE, it means the property name or ID
    // had valid syntax, but it didn't exist in this property set, so
    // no properties were retrieved, and each PROPVARIANT structure is set 
    // to VT_EMPTY. But the following switch statement will handle this case
    // and return E_FAIL. So the caller of ReadPropertyLong does not need
    // to check for S_FALSE explicitly.

    if (SUCCEEDED(hr))
    {
        hr = S_OK;

        switch (PropVariant.vt)
        {
        case VT_I1:	*plResult = (LONG) PropVariant.cVal;				break;

        case VT_UI1:	*plResult = (LONG) PropVariant.bVal;				break;

        case VT_I2:	*plResult = (LONG) PropVariant.iVal;				break;

        case VT_UI2:	*plResult = (LONG) PropVariant.uiVal;				break;

        case VT_I4:	*plResult = (LONG) PropVariant.lVal;				break;

        case VT_UI4:	*plResult = (LONG) PropVariant.ulVal;				break;

        case VT_INT:	*plResult = (LONG) PropVariant.intVal;				break;

        case VT_UINT:	*plResult = (LONG) PropVariant.uintVal;				break;

        case VT_R4:	*plResult = (LONG) (PropVariant.fltVal + 0.5);		break;

        case VT_R8:	*plResult = (LONG) (PropVariant.dblVal + 0.5);		break;

        default:
            hr = E_FAIL;
            break;
        }
    }

    PropVariantClear(&PropVariant);

    return hr;
}

HRESULT ReadPropertyGuid( IWiaPropertyStorage *pWiaPropertyStorage, const PROPSPEC *pPropSpec, GUID *pguidResult )
{
    PROPVARIANT PropVariant;

    HRESULT hr = pWiaPropertyStorage->ReadMultiple( 1, pPropSpec, &PropVariant );

    // Generally, the return value should be checked against S_FALSE.
    // If ReadMultiple returns S_FALSE, it means the property name or ID
    // had valid syntax, but it didn't exist in this property set, so
    // no properties were retrieved, and each PROPVARIANT structure is set 
    // to VT_EMPTY. But the following switch statement will handle this case
    // and return E_FAIL. So the caller of ReadPropertyGuid does not need
    // to check for S_FALSE explicitly.

    if (SUCCEEDED(hr))
    {
        switch (PropVariant.vt)
        {
        case VT_CLSID:
            {
                *pguidResult = *PropVariant.puuid; 

                hr = S_OK;

                break;
            }

        case VT_BSTR:
            {
                hr = CLSIDFromString(PropVariant.bstrVal, pguidResult);

                break;
            }

        case VT_LPWSTR:
            {
                hr = CLSIDFromString(PropVariant.pwszVal, pguidResult);

                break;
            }

        case VT_LPSTR:
            {
                WCHAR wszGuid[MAX_GUID_STRING_LEN];
                mbstowcs_s(NULL, wszGuid, MAX_GUID_STRING_LEN, PropVariant.pszVal, MAX_GUID_STRING_LEN);

                wszGuid[MAX_GUID_STRING_LEN - 1] = L'\0';

                hr = CLSIDFromString(wszGuid, pguidResult);

                break;
            }

        default:
            {
                hr = E_FAIL;

                break;
            }
        }
    }

    PropVariantClear(&PropVariant);

    return hr;
}

HRESULT WritePropertyLong( IWiaPropertyStorage *pWiaPropertyStorage, const PROPSPEC *pPropSpec, LONG lValue )
{
    PROPVARIANT prop;
    prop.vt = VT_I4;
    prop.intVal = lValue;

    HRESULT hr = pWiaPropertyStorage->WriteMultiple( 1, pPropSpec, &prop, WIA_IPA_FIRST );

    return hr;
}

HRESULT WiaGetNumDevices( IWiaDevMgr *pSuppliedWiaDevMgr, ULONG *pulNumDevices )
{
    HRESULT hr;

    // Validate and initialize output parameters

    if (pulNumDevices == NULL)
    {
        return E_POINTER;
    }

    *pulNumDevices = 0;

    // Create a connection to the local WIA device manager

    CComPtr<IWiaDevMgr> pWiaDevMgr = pSuppliedWiaDevMgr;

    if (pWiaDevMgr == NULL)
    {
        hr = pWiaDevMgr.CoCreateInstance(CLSID_WiaDevMgr);

        if (FAILED(hr))
        {
            return hr;
        }
    }

    // Get a list of all the WIA devices on the system

    CComPtr<IEnumWIA_DEV_INFO> pIEnumWIA_DEV_INFO;

    hr = pWiaDevMgr->EnumDeviceInfo( 0, &pIEnumWIA_DEV_INFO );

    if (FAILED(hr))
    {
        return hr;
    }

    // Get the number of WIA devices

    ULONG celt;

    hr = pIEnumWIA_DEV_INFO->GetCount(&celt);

    if (FAILED(hr))
    {
        return hr;
    }

    *pulNumDevices = celt;

    return S_OK;
}

HRESULT CALLBACK DefaultProgressCallback( LONG   lStatus, LONG   lPercentComplete, PVOID  pParam )
{

    return S_OK;
}

